#ifndef CASEDB_CONNECTION_HPP
#define CASEDB_CONNECTION_HPP

#include "CaseDB/CaseDbConfig.hpp"
#include <string>
#include <cstddef>

namespace CaseDB
{

namespace Impl { class ConnectionImpl; }
class Statement;
class RecordSet;

/// \ingroup CaseDB
/// \brief It implements a database connection.
/// 
/// The database connection knows to execute various statements. It also provides methods for opening and closing the 
///	connection to the described database. 
/// \par
/// Depending on the database vendor, there are subclasses that accept various construction parameters that will be used 
///	for setting up the connection. It was done like this because different connections may need different parameters.
/// \par Design considerations
/// In order to hide implementation details (and header dependencies) from outside this module, a pImpl idiom was used. 
///	Impl::ConnectionImpl class and its subclasses are actually implementing the functionality. This class only delegates 
///	function calls to the implementation object.
class CASEDB_API Connection
{
protected:
	/// \brief It initializes the connection.
	/// \param name the name of the connection.
	/// \param pImpl the connection implementation object to be used.
	///
	/// This constructor can be used only by the subclasses to initialize. It is the responsibility of the subclasses to 
	///	create the implementation object and to pass it to this constructor for initialization of this class members.
	/// \pre The specified implementation object is not NULL.
	explicit Connection( const std::string& name, Impl::ConnectionImpl* pImpl);

public:
	/// \brief It deletes the implementation object.
	virtual ~Connection();

	/// \brief It opens the database connection.
	///
	/// By default, it only delegates the call to the implementation object.
	/// \exception DatabaseError thrown if the connection to the database couldn't be established.
	virtual void open();

	/// \brief It closes the database connection.
	///
	/// By default, it only delegates the call to the implementation object.
	virtual void close();

	/// \brief It executes the specified statement.
	/// 
	/// After execution, the output parameter values will be set back to the statement object.
	/// \param statement the statement to be executed.
	/// \sa CaseDB::Statement
	/// \sa CaseDB::Impl::ConnectionImpl::execute( Statement&)
	void execute( Statement& statement);

	/// \brief It executes the specified query.
	/// 
	/// After execution, the output parameter values will be set back to the statement object.
	/// \param statement the query statement to be executed.
	/// \param results the recordset that will contain the results of the query.
	/// \sa CaseDB::Statement
	/// \sa CaseDB::RecordSet
	/// \sa CaseDB::Impl::ConnectionImpl::execute( Statement&, RecordSet&)
	void execute( Statement& statement, RecordSet& results);

protected:
	Impl::ConnectionImpl* pImpl_;
};

} // namespace CaseDB

#endif // CASEDB_CONNECTION_HPP
